from flask import Flask, render_template, request, send_from_directory, redirect, url_for,jsonify, send_file
import os
import sys
import signal
from VideoInfoDb import VideoInfoDb
from websockets.sync.client import connect
import json

class PreviewVideoPage:
    def __init__(self, video_folder, ip_address, port=5342):
        video_folder = os.path.abspath(video_folder)
        self.video_folder = video_folder
        self.ip_address = ip_address
        self.port = port
        self.allowed_extensions = {"mp4", "avi", "mov", "mkv"}

        if not os.path.exists(self.video_folder):
            os.makedirs(self.video_folder)

        self.db_path = os.path.join(self.video_folder, "video_info.json")
        self.db = VideoInfoDb(self.db_path)

        self.app = Flask(__name__)
        self._setup_routes()

    def _setup_routes(self):
        self.app.add_url_rule("/", view_func=self.index)
        self.app.add_url_rule("/videos/<filename>", view_func=self.video)
        self.app.add_url_rule("/delete/<filename>", view_func=self.delete_video, methods=["POST"])
        self.app.add_url_rule("/reset_scene", view_func=self.reset_scene, methods=["POST"])
        self.app.add_url_rule("/get_bag/<filename>", view_func=self.get_bag)
        self.app.add_url_rule("/download_bag/<filename>", view_func=self.download_bag)
    def allowed_file(self, filename):
        return "." in filename and filename.rsplit(".", 1)[1].lower() in self.allowed_extensions
    def reset_scene(self):
        uri = "ws://localhost:8765"
        try:
            # Establish a blocking connection
            with connect(uri, open_timeout=60.0, close_timeout=60.0) as websocket:
                # Prepare and send the message
                message = {"type": "reset"}
                websocket.send(json.dumps(message))            
                # Receive and process the response
                response = websocket.recv()

        except Exception as e:
            print("Failed to reset the scene:", e)
        return jsonify({"status": "success"})
    def index(self):
        return self.refresh()

    def video(self, filename):
        return send_from_directory(self.video_folder, filename)

    def delete_video(self, filename):
        file_path = os.path.join(self.video_folder, filename)
        if os.path.exists(file_path):
            os.remove(file_path)
            self.db.delete_by_video_path(file_path)
            print(f"Deleted {filename}")
        else:
            print(f"File {filename} not found.")
        return redirect(url_for("index"))

    def get_bag(self, filename):
        """检查对应 bag 文件是否存在"""
        bag_path = self.db.get_video_bags(os.path.join(self.video_folder, filename))
        print(bag_path)
        if bag_path is None or os.path.exists(bag_path):
            return jsonify({"exists": True, "path": os.path.abspath(bag_path)})
        else:
            return jsonify({"exists": False})

    def download_bag(self, filename):
        """下载 bag 文件"""
        bag_path = self.db.get_video_bags(os.path.join(self.video_folder, filename))
        if bag_path is not None or os.path.exists(bag_path):
            return send_file(bag_path, as_attachment=True)
        return "File not found", 404

    def refresh(self):
        origin_tags = request.args.get("tags", "")
        tags = origin_tags.split(",") if request.args.get("tags") else []
        if tags:
            video_files, all_tags = self.db.search_videos_by_tags(tags)
            video_files = [os.path.basename(f) for f in video_files if os.path.exists(f)]
        else:
            video_files = [f for f in os.listdir(self.video_folder) if self.allowed_file(f)]
            all_tags = self.db.get_all_tags()
        # hide tags start with iter
        filtered_tags = [tag for tag in all_tags if not tag.startswith("iter")]
        filtered_tags = sorted(filtered_tags)
        filtered_tags = sorted(tags) + filtered_tags
        video_files = sorted(video_files, reverse=True)
        page = int(request.args.get("page", 1))
        per_page = 20
        start = (page - 1) * per_page
        end = start + per_page
        videos = video_files[start:end]

        videos_info = []
        for video in videos:
            video_path = os.path.join(self.video_folder, video)
            video_tags = self.db.get_video_tags(video_path)
            videos_info.append({"name": video, "tags": video_tags})

        total_pages = (len(video_files) + per_page - 1) // per_page
        
        return render_template(
            "index.html",
            all_tags=filtered_tags,
            video_infos=videos_info,
            videos_folder=self.video_folder,
            total_pages=total_pages,
            current_page=page,
            current_tags=tags,
            origin_tags=origin_tags
        )

    def run(self):
        def stop_handler(*args):
            print("Stopping server...")
            self.db.close()
            sys.exit(0)

        signal.signal(signal.SIGINT, stop_handler)
        self.app.run(debug=False, host=self.ip_address, port=self.port)
        self.db.close()


if __name__ == "__main__":
    video_folder = sys.argv[1]
    ip_address = sys.argv[2]
    preview_video_page = PreviewVideoPage(video_folder, ip_address)
    preview_video_page.run()
